<?php

class Pageley_Reflection_ProxyFactoryTests extends Pageley_Test_Case {
    
    private $invocationHandler;
    
    public function setUp() {
        $this->invocationHandler = new Pageley_Reflection_InvocationHandlerMock();
    }
    
    public function testGenerateClass() {
        $factory = new Pageley_Reflection_ProxyFactory();
        $code = $factory->generateClass(new Pageley_Util_ArrayMap(
                new ReflectionClass("Pageley_Reflection_TestInterface1"), 
                new ReflectionClass("Pageley_Reflection_TestInterface2")
            ), "TestProxy");
        $expectedCode = "class TestProxy extends Pageley_Reflection_Proxy implements Pageley_Reflection_TestInterface1, Pageley_Reflection_TestInterface2 {\n" .
            "\n" .
            "    public function simpleMethod() {\n" .
            "        \$parameters = new Pageley_Util_ArrayMap();\n" .
            "        \$result = \$this->__invokeMethod(\"simpleMethod\", \$parameters);\n" .
            "        return \$result;\n" .
            "    }\n" .
            "\n" .
            "\n" .
            "    public function methodWithParameters(&\$parameter1, \$parameter2 = 'value', \$parameter3 = null) {\n" .
            "        \$parameters = new Pageley_Util_ArrayMap(\$parameter1, \$parameter2, \$parameter3);\n" .
            "        \$result = \$this->__invokeMethod(\"methodWithParameters\", \$parameters);\n" .
            "        \$parameter1 = \$parameters->get(0);\n" .
            "        return \$result;\n" .
            "    }\n" .
            "\n" .
            "\n" .
            "    public function method2() {\n" .
            "        \$parameters = new Pageley_Util_ArrayMap();\n" .
            "        \$result = \$this->__invokeMethod(\"method2\", \$parameters);\n" .
            "        return \$result;\n" .
            "    }\n" .
            "\n" .
            "\n" .
            "    public function method3() {\n" .
            "        \$parameters = new Pageley_Util_ArrayMap();\n" .
            "        \$result = \$this->__invokeMethod(\"method3\", \$parameters);\n" .
            "        return \$result;\n" .
            "    }\n" .
            "\n" .
            "\n" .
            "    public function __toString() {\n" .
            "        return \"TestProxy\";\n" .
            "    }\n" .
            "\n" .
            "}\n";
        $this->assertEquals($expectedCode, $code);
    }
    
    public function testCreateProxy() {
        $invocationHandlerMock = new Pageley_Reflection_InvocationHandlerMock();
        
        $factory = new Pageley_Reflection_ProxyFactory();
        $proxy = $factory->createProxy(
            new Pageley_Util_ArrayMap("Pageley_Reflection_TestInterface1"),
            $invocationHandlerMock);
        $this->assertNotNull($proxy);
        $this->assertEquals("Pageley_Reflection_TestInterface1__Proxy0", get_class($proxy));
        
        $invocationHandlerMock->invoke($proxy, "simpleMethod", new Pageley_Util_ArrayMap())->andReturn("result");
        $changeA = new Pageley_Reflection_ParameterChanger(0, "b");
        $invocationHandlerMock->invoke($proxy, "methodWithParameters", new Pageley_Util_ArrayMap("a", "b", "c"))->andExecute($changeA);
        $invocationHandlerMock->replay();
        
        $this->assertEquals("result", $proxy->simpleMethod());
        $a = "a";
        $proxy->methodWithParameters($a, "b", "c");
        $this->assertEquals("b", $a);
    }
    
    public function testCreateProxyReuseClass() {
        $invocationHandlerMock = new Pageley_Reflection_InvocationHandlerMock();
        
        $factory = new Pageley_Reflection_ProxyFactory();
        $proxy1 = $factory->createProxy(
            new Pageley_Util_ArrayMap("Pageley_Reflection_TestInterface2"),
            $invocationHandlerMock);
        $this->assertNotNull($proxy1);
        $this->assertEquals("Pageley_Reflection_TestInterface2__Proxy0", get_class($proxy1));
        
        $proxy2 = $factory->createProxy(
            new Pageley_Util_ArrayMap("Pageley_Reflection_TestInterface2"),
            $invocationHandlerMock);
        $this->assertNotNull($proxy2);
        $this->assertEquals("Pageley_Reflection_TestInterface2__Proxy0", get_class($proxy2));
    }
    
    public function testCreateProxyCreateNewClass() {
        $invocationHandlerMock = new Pageley_Reflection_InvocationHandlerMock();
        
        $factory = new Pageley_Reflection_ProxyFactory();
        $proxy1 = $factory->createProxy(
            new Pageley_Util_ArrayMap("Pageley_Reflection_TestInterface3"),
            $invocationHandlerMock);
        $this->assertNotNull($proxy1);
        $this->assertEquals("Pageley_Reflection_TestInterface3__Proxy0", get_class($proxy1));
        
        $proxy2 = $factory->createProxy(
            new Pageley_Util_ArrayMap("Pageley_Reflection_TestInterface3", "Pageley_Reflection_TestInterface1"),
            $invocationHandlerMock);
        $this->assertNotNull($proxy2);
        $this->assertEquals("Pageley_Reflection_TestInterface3__Proxy1", get_class($proxy2));
    }
}